library AXY_UDPSender;

{ Format of messages are command=value }

uses
  System.SysUtils,
  System.Classes,
  IdBaseComponent,
  IdComponent,
  IdUDPBase,
  IdUDPClient
  ;

{$R *.res}

const
  C_Version= '0.1';
  C_Response_unknown= 'unk';

  C_LogFile= 'E:\Temp\AXY_UDPSender.log';

  CMD_SetIP= 'server';
  CMD_SendUpdate= 'newpos';
  CMD_Version= 'version';


var
  UdpSocket: TIdUDPClient;    // Using the Indy Client UDP Component.

// Debugging logging function.
function logMessage(const logMsg: String): Boolean;
var
  logFile: TextFile;
begin
  {$IFDEF DEBUG}
    AssignFile(logFile, C_LogFile);
    if FileExists(C_LogFile) then
      Append(logFile)
    else
      Rewrite(logFile);
    try
      Writeln(logFile, formatDateTime('yyyymmdd hh:nn:ss', now)+ ' - '+ logMsg);
    finally
      CloseFile(logFile);
    end;
  {$ENDIF}
  Result:= True;
end;

{ Sets up the IP to send the UDP messages to. }
function handleSetIP(toArmA: PAnsiChar; outputSize: Integer; fromArmA: String): Boolean;
var
  udpPort: Word;
  udpHost: String;
begin
  { We're expecting a hostaddress:port }
  logMessage('Processing SetIP');
  if pos(':', fromArmA)> 0 then
  begin
    udpPort:= StrtoInt(copy(fromArmA, pos(':', fromArmA)+ 1));
    udpHost:= copy(fromArmA, pos('=', fromArmA)+ 1, length(fromArmA));
    udpHost:= copy(udpHost, 1, pos(':', udpHost)- 1);

    logMessage('Setting server details to '+ udpHost+ ':'+ InttoStr(udpPort));
    udpSocket.Host:= udpHost;
    udpSocket.Port:= udpPort;

    strCopy(toArmA, 'ok');
    Result:= true;
  end
  else
  begin
    logMessage('Message format error.');
    strCopy(toArmA, 'formaterror');
    result:= False;
  end;
end;  // End of handleSetIP function.

{ Sends off the received data to the UDP Server. }
function handleSendUpdate(toArmA: PAnsiChar; outputSize: Integer; fromArmA: String): Boolean;
begin
  { Do we filter the content first? }
  logMessage('sendUpdate');
  { TODO This needs to be cleaned up }
  udpSocket.Send(copy(fromArmA, pos('=', fromArmA)+ 1, length(fromArmA)));
  strCopy(toArmA, 'ok');
  Result:= True;
end;  // End of handleSetIP function.


{ Just returning the version of the extension. }
function handleGetVersion(toArmA: PAnsiChar; outputSize: Integer): Boolean;
begin
  strcopy(toARmA, C_Version);
  Result:= True;
end;

{Returns/Logs that we have nfi what the caller sent.}
function handleUnknown(toArmA: PAnsiChar; outputSize: Integer): Boolean;
begin
  logMessage('No recognised command sent.');
  strcopy(toArmA, C_Response_unknown);
  Result:= True;
end;

{ Entry Point from ArmA }
procedure RVExtension(toArmA: PAnsiChar; outputSize: Integer; fromArma: PAnsiChar); stdcall; export;
begin
  // A3 can send us a few params.
  try
    LogMessage('Received '+ fromArmA);
    if copy(fromArma, 1, Length(CMD_SetIP))= CMD_SetIP then
      handleSetIP(toArmA, outputSize, fromArmA)
    else if copy(fromArma, 1, Length(CMD_SendUpdate))= CMD_SendUpdate then
      handleSendUpdate(toArmA, outputSize, fromArmA)
    else if copy(fromArma, 1, Length(CMD_Version))= CMD_Version then
      handleGetVersion(toArmA, outputSize)
    else
      handleUnknown(toArma, outputSize);
  except
    // Don't want to send exceptions back to the A3 client...
   LogMessage('Exception: '+ Exception(ExceptObject).Message);

  end;
end;

exports
  RVExtension name '_RVExtension@12';

begin
  // Create the socket on init.
  UdpSocket:= TIdUDPClient.Create(nil);

end.
